package mysql

import (
	"errors"
	"fmt"
	"gitee.com/captials-team/ubdframe/src/domain/configstc"
	"gitee.com/captials-team/ubdframe/src/domain/interfaces"
	"gitee.com/captials-team/ubdframe/src/domain/models"
	mysqlClients "gitee.com/captials-team/ubdframe/src/infrastructure/clients/mysql"
	"gorm.io/gorm"
	"strings"
	"time"
)

func NewSettingDao(conf configstc.DBConfig) *SettingDao {
	return &SettingDao{
		db:   mysqlClients.NewGormDB(conf),
		conf: conf,
	}
}

type SettingDao struct {
	db   *gorm.DB
	conf configstc.DBConfig
}

func (dao *SettingDao) Set(key, value string) error {
	ret := dao.db.Exec(
		fmt.Sprintf("INSERT INTO `%s` (`created_at`,`key`,`value`) VALUES (?,?,?) ON DUPLICATE KEY UPDATE `value` = ?,`updated_at`=?;",
			new(models.Setting).TableName(dao.db.NamingStrategy)),
		time.Now(), key, value, value, time.Now())

	return ret.Error
}

func (dao *SettingDao) Get(key string) (string, error) {
	var info models.Setting

	ret := dao.db.Where("`key`=?", key).Select("value").First(&info)
	if errors.Is(ret.Error, gorm.ErrRecordNotFound) {
		return "", nil
	} else if ret.Error != nil {
		return "", ret.Error
	}
	return info.Value, nil
}

func (dao *SettingDao) SetMulti(data map[string]string) error {
	var values []string
	var binds []interface{}
	for k, v := range data {
		values = append(values, "(?,?,?)")
		binds = append(binds, time.Now(), k, v)
	}
	sql := fmt.Sprintf(
		"INSERT INTO `%s` (`created_at`,`key`,`value`) VALUES %s ON DUPLICATE KEY UPDATE `value` = VALUES(value),`updated_at`=VALUES(updated_at)",
		new(models.Setting).TableName(dao.db.NamingStrategy),
		strings.Join(values, ","),
	)
	ret := dao.db.Exec(sql, binds...)
	return ret.Error
}

func (dao *SettingDao) GetMulti(keys ...string) (map[string]string, error) {
	var list []*models.Setting
	if ret := dao.db.Where("`key` in (?)", keys).Find(&list); ret.Error != nil {
		return nil, ret.Error
	}

	m := map[string]string{}
	for _, v := range list {
		m[v.Key] = v.Value
	}

	return m, nil
}

func (dao *SettingDao) Migrate() (int64, error) {
	return 1, dao.db.AutoMigrate(new(models.Setting))
}

func (dao *SettingDao) DB() *gorm.DB {
	return dao.db
}

func (dao *SettingDao) Use(db *gorm.DB) interfaces.ItfSettingDao {
	return &SettingDao{
		db:   db,
		conf: dao.conf,
	}
}
